package com.hong.demo.other.fsm;

import com.hong.demo.other.fsm.impl.ApplyForRefundTransition;
import com.hong.demo.other.fsm.impl.BuyerPayTransition;
import com.hong.demo.other.fsm.impl.GoodsForRefundTransition;
import com.hong.demo.other.fsm.impl.OrderEvent;
import com.hong.demo.other.fsm.impl.OrderState;
import com.hong.demo.other.fsm.inf.IFSMTransition;
import com.hong.demo.other.fsm.inf.IFSMTransitionBlock;

import java.util.HashMap;
import java.util.Map;

/**
 * https://xie.infoq.cn/article/79c042686f2412f05e4119d8a
 */
public class StateMachine {
    private String name;
    // 当前状态，事件，业务处理逻辑(返回目标状态)
    private Map<OrderState, Map<OrderEvent, IFSMTransition>> handle = new HashMap<>();
    private IFSMTransitionBlock ifsmTransitionBlock;

    public StateMachine() {
        handle.put(OrderState.WAIT_PAY, new HashMap<OrderEvent, IFSMTransition>() {{
            put(OrderEvent.PAY, new BuyerPayTransition());
        }});

        handle.put(OrderState.PAYED, new HashMap<OrderEvent, IFSMTransition>() {{
            put(OrderEvent.APPLY_FOR_REFUND, new ApplyForRefundTransition());
            put(OrderEvent.APPLY_FOR_RETURN_GOODS, new GoodsForRefundTransition());
        }});
    }

    /**
     * 启动状态机
     */
    public void fire(IFSMContext context) {
        Map<OrderEvent, IFSMTransition> handleMap = handle.get(context.getSourceState());
        if (handleMap != null) {
            for (Map.Entry<OrderEvent, IFSMTransition> entry : handleMap.entrySet()) {
                OrderEvent orderEvent = entry.getKey();
                IFSMTransition iFSMTransition = entry.getValue();
                if (orderEvent == context.getEvent()) {
                    iFSMTransition.onTransition(context);
                }
            }
        }

        // 状态机无法处理情况，托底逻辑
        ifsmTransitionBlock.onTransitionBlock(context);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public IFSMTransitionBlock getIfsmTransitionBlock() {
        return ifsmTransitionBlock;
    }

    public void setIfsmTransitionBlock(IFSMTransitionBlock ifsmTransitionBlock) {
        this.ifsmTransitionBlock = ifsmTransitionBlock;
    }
}
